import React, { useContext, useEffect, useState, useMemo } from 'react';
import { Table, Select, Descriptions, Card, Row, Col, Button, Modal } from 'antd';
import { connect } from 'dva';
import isObject from 'lodash/isObject';
import sortBy from 'lodash/sortBy';

import PateoTable from '@/components/common/PateoTable';
import { downloadFileByUrl } from '@/utils/utils';
import { findDicByCode } from '@/support/common';
import CommonContext from '@/layouts/CommonContext';

import { convertObjToArray, filterOutAnomalyData } from './utils';
import MessageDisplay from './messageDisplay';
import ValueDisplay from './valueDisplay';

type messageTabProps = {
  vehicleInfoQuery: any;
  dispatch: any;
  reportTime: string;
  goBack: () => void;
};

type MessageType = {
  vin: string;
  reportTime: string;
  message: string;
};

interface CommonContext {
  dicData: any[];
}

interface DictItem {
  dictValue: string;
  dictKey: string;
  dictDesc: string;
}

interface MessageItem {
  splitter: string;
  field: string;
  chinese: string;
  value: string;
}
const DEFAULT_FILTER = () => ({
  dataView: 'full',
});

const logTab: React.FC<messageTabProps> = props => {
  const { reportTime, vehicleInfoQuery, goBack, dispatch } = props;
  const { vin } = vehicleInfoQuery;

  const [message, setMessage]: [MessageType, Function] = useState({
    vin,
    reportTime: '',
    message: '',
  });

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [modalContent, setModalContent] = useState('');
  const [loading, setLoading] = useState(false);
  const closeModal = () => {
    setModalContent('');
    setIsModalOpen(false);
  };

  const { dicData } = useContext(CommonContext) as CommonContext;

  const messageEncodingDict = (
    findDicByCode(dicData as DictItem[], 'messageEncoding') || []
  ).reduce((acc: { [key: string]: DictItem }, { dictValue, dictKey, dictDesc }: DictItem) => {
    acc[dictKey] = {
      dictValue,
      dictKey,
      dictDesc,
    };
    return acc;
  }, {});

  const fetchMessageDetail = async () => {
    setLoading(true);
    const { data } = await dispatch({
      type: 'message/getFetchPage',
      payload: {
        url: '/message/parsing/detail',
        vin: vehicleInfoQuery.vin,
        reportTime,
      },
    });
    setLoading(false);
    console.log(data);
    setMessage(data);
  };

  const [filter, setFilter] = useState(DEFAULT_FILTER());

  useEffect(() => {
    fetchMessageDetail();
  }, [vin, reportTime]);

  const messageData = useMemo(() => {
    return JSON.parse(message.message || '{}');
  }, [message]);

  const dataSource = useMemo((): MessageItem[] => {
    const list: { key: string; value: string }[] = convertObjToArray(
      filter.dataView === 'anomaly' ? filterOutAnomalyData(messageData) : messageData,
    );
    return list.reduce((acc: MessageItem[], { key, value }) => {
      if (messageEncodingDict[key]) {
        const { dictValue, dictKey, dictDesc } = messageEncodingDict[key];
        acc.push({
          splitter: dictValue,
          field: dictKey,
          chinese: dictDesc,
          value,
        });
      }
      return acc;
    }, []);
  }, [filter, messageData]);

  const columns = [
    {
      title: '序号',
      dataIndex: 'index',
    },
    {
      title: '分隔符',
      dataIndex: 'splitter',
    },
    {
      title: '字段',
      dataIndex: 'field',
    },
    {
      title: '中文名称',
      dataIndex: 'chinese',
    },
    Table.EXPAND_COLUMN,
    {
      title: '值',
      dataIndex: 'value',
      render: (value: Object | String | undefined) => {
        const showJsonContent = () => {
          setModalContent(JSON.stringify(value, null, 4));
          setIsModalOpen(true);
        };
        return isObject(value) ? (
          <Button onClick={showJsonContent}>原始数据</Button>
        ) : (
          <ValueDisplay value={value} />
        );
      },
    },
  ];

  const tableProps = {
    columns, // 列
    rowKey: record => record.splitter, // key
    loading, // 控制加载
    // bordered: true, // 边框
    selectedRows: [],
    dataSource: sortBy(dataSource, row => row.splitter).map((row, index) => ({
      ...row,
      index: index + 1,
    })),
    expandable: {
      expandedRowRender: record => {
        return <MessageDisplay record={record} messageEncodingDict={messageEncodingDict} />;
      },
      rowExpandable: record => {
        return isObject(record.value);
      },
    },
    pagination: false,
  };

  const downloadAttachmentFile = async () => {
    const res = await dispatch({
      type: 'vehicleInfoQuery/getFetchPage',
      // 管理员 -> 模板管理
      payload: { url: '/common/template/detail', templateCode: 'messageAttachment' },
    });
    const { data } = res;
    const templateUrl = data.templateUrl;
    downloadFileByUrl(templateUrl, '附表.xlsx');
  };

  return (
    <>
      <Card bordered={false} loading={loading}>
        <Button key="back" type="primary" size="small" onClick={goBack}>
          返回
        </Button>
        <Descriptions bordered style={{ margin: '10px 0', overflow: 'hidden' }}>
          <Descriptions.Item span={1} label="VIN">
            {message.vin}
          </Descriptions.Item>
          <Descriptions.Item span={2} label="上报时间">
            {message.reportTime}
          </Descriptions.Item>
          <Descriptions.Item span={3} label="原始报文">
            <code>{messageData.originalMessage}</code>
          </Descriptions.Item>
        </Descriptions>
      </Card>
      <Card bordered={false} loading={loading}>
        <Row align="middle" style={{ margin: '10px 0' }}>
          <Col flex="100px">报文数据</Col>
          <Col flex="140px">
            <Select
              defaultValue="full"
              style={{ width: 120 }}
              onChange={(value: string) => setFilter({ dataView: value })}
              options={[
                { value: 'full', label: '全部数据' },
                { value: 'anomaly', label: '异常数据' },
              ]}
            />
          </Col>
          <Col flex="100px">
            <Button type="primary" onClick={downloadAttachmentFile}>
              下载附表
            </Button>
          </Col>
        </Row>
        <Modal width={'80vw'} visible={isModalOpen} onOk={closeModal} onCancel={closeModal}>
          <code style={{ whiteSpace: 'pre' }}>{modalContent}</code>
        </Modal>
        <PateoTable
          extraHandle={true}
          tableProps={tableProps}
          dispatch={dispatch}
          formValues={{}}
          currentName="curPage"
        />
      </Card>
    </>
  );
};

export default connect(({ vehicleInfoQuery }) => ({
  vehicleInfoQuery,
}))(logTab);
